﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Scribe4net
{


    public class XmlSerializationWriter : ISerializationWriter
    {

        StringBuilder sb = new StringBuilder();
        string _indent = "  ";
        public void Start(string objName, bool isList)
        {
        }

        public int IndentationLevel { get; set; }

        private void WriteIndentation()
        {
            for (int i = 0; i < IndentationLevel; ++i)
            {
                sb.Append(_indent);
            }
        }

        public virtual void ListStart(string listObjectName, int dept, bool oneLiner)
        {
            WriteIndentation();
            if (listObjectName.ToLower().Contains("[]"))
                sb.Append("<Array>");
            else
                sb.Append("<List>");

            if (!oneLiner)
                sb.AppendLine();
        }

        public virtual void ListEnd(string listObjectName, int dept)
        {
            if (sb[sb.Length - 1] == '\n')
                WriteIndentation();
            if (listObjectName.ToLower().Contains("[]"))
                sb.AppendLine("</Array>");
            else
                sb.AppendLine("</List>");
        }

        public void ListItemStart(string listItemObjectName, int dept, bool oneLiner)
        {
            if (oneLiner)
            {
                WriteIndentation();
                sb.Append("<");
                sb.Append(ApplyXmlEscaping(listItemObjectName));
                sb.Append(">");
            }
        }

        public void ListItemEnd(string listItemObjectName, int dept, bool oneLiner)
        {
            if (oneLiner)
            {
                sb.Append("</");
                sb.Append(ApplyXmlEscaping(listItemObjectName));
                sb.AppendLine(">");
            }
        }

        public void DictStart(string dictObjectName, int dept, bool oneLiner)
        {
            WriteIndentation();
            sb.AppendLine("<" + ApplyXmlEscaping(dictObjectName) + ">");
        }

        public void DictEnd(string dictObjectName, int dept)
        {
            WriteIndentation();
            sb.AppendLine("</" + ApplyXmlEscaping(dictObjectName) + ">");
        }

        public void DictItemStart(string dictItemObjectName, int dept, bool oneLiner)
        {
            WriteIndentation();
            sb.Append("<" + ApplyXmlEscaping(dictItemObjectName) + ">");
            if (!oneLiner)
                sb.AppendLine();
        }

        public void DictItemEnd(string dictItemObjectName, int dept)
        {
            if (sb[sb.Length - 1] == '\n')
                WriteIndentation();

            sb.AppendLine("</" + ApplyXmlEscaping(dictItemObjectName) + ">");
        }

        public void ObjectStart(string objectName, int dept, bool oneLiner)
        {
            WriteIndentation();
            sb.AppendLine("<" + ApplyXmlEscaping(objectName) + ">");
        }

        public void ObjectEnd(string objectName, int dept)
        {
            WriteIndentation();
            sb.AppendLine("</" + ApplyXmlEscaping(objectName) + ">");
        }

        public void End(string objName)
        {
        }

        public string GetString()
        {
            return sb.ToString();
        }


        public void AppendPrimitiveValue(object valueToAppend, int dept)
        {
            if (valueToAppend == null)
            {
                //sb.Remove(sb.Length - 1, 1);
                WriteIndentation();
                sb.AppendLine("<Object nil=\"true\" />");
            }
            else
            {
                sb.Append(valueToAppend.ToString());
            }
        }

        public void AppendNullValue(string name, int dept, bool inList)
        {
            WriteIndentation();
            sb.AppendLine("<" + name + " nil=\"true\" />");
        }

        string ApplyXmlEscaping(string strOriginal)
        {
            string strAfterReplace =  Regex.Replace(strOriginal, @"[\#\{\}\&\(\)\[\]\^\<\>]*", "");
            return strAfterReplace;
            //return SecurityElement.Escape(strAfterReplace);
        }
    }
}
